# -*- coding:utf-8 -*-
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
# from django.contrib import auth
from django.contrib import messages

from models import *
import json
# delete nwo_list any whitespace character
import re


@login_required()
# default index show
def get_hosts(request):
    """
    Now I didn't do this action --- Base on customer_id, query all info archived to redis server.
    Show hosts list and services name,

    The show of service parameters base on ser_dict.
    for service_name, service_value in ser_dict.items():
        #<text>{{service_name}}</text>
        for host_name,host_service_parameters  service_value.items():
            # <td> {{host_name}} </td>
            for parameter_key, parameter_value in host_service_parameters.items():
                print parameter_key,  parameter_value
    """
    # customer_id = "123"
    customer_id = request.session.get('customerId')
    customer_name = request.session.get('customerName')
    account_name =  request.session.get('userName')
    customer_id = "123"
    info = []
    for host in Host.objects(customer_id=customer_id):
        info.append(host)
    ser_dict = {}
    for host_info in info:
        for s in host_info.service.keys():
            if s in ser_dict.keys():
                ser_dict[s][host_info._id] = host_info.service[s]
            else:
                ser_dict[s]={host_info._id: host_info.service[s]}
    return render(request, "services_index.html", {"content": info, "services": ser_dict, "customer_name": customer_name, "account_name": account_name})


def verify_host(request):
    """
    verify host whether in the collections.
    """
    content = request.POST
    if Host.objects(_id=content["host_name"]).count() > 0:
        messages.warning(request, '该主机已经存在于帐户下, 可至首页更新该主机信息!')
        return HttpResponse(1)
    else:
        return HttpResponse(0)


def get_service_default(service_name):
    try:
        default_ser = Service.objects(_id=service_name)[0]
    except IndexError:
        return False
    return default_ser.parameters


def get_service_key(host_id):
    host_info = Host.objects(_id=host_id)[0]
    service_list = host_info.service.keys()
    if not service_list:
        return False
    return service_list


@login_required()
def add_host(request):
    """
    customer_id, host_name, services
    request.GET["customer_id"]
    request.GET["host_name"]

    db.collection.insert({
        "customer_id" : "112",
        "hostname" : "srv-nc-test3",
        "services": {
            "service_name": {"default_parameters": "default_values" },
            "mysql": { "listen_port": "3306", ... }
            }
    })
    """
    if request.method == "POST":
        content = request.POST
        # because of service is not required
        service_dict = {}
        if "service" in content.keys():
            services = [i for i in content["service"].split(',') if i.strip()]
            for ser_name in services:
                try:
                    default_ser = Service.objects(_id=ser_name.strip())[0]
                    service_dict[ser_name.strip()] = default_ser.parameters
                except IndexError:
                    warning_info = "It's not support " + ser_name.strip() + " service install."
                    messages.warning(request, warning_info)
                    service_dict[ser_name.strip()] = {}
        # insert document
        # try:
        Host(_id=content["host_name"], customer_id="123", ip=content["ip"], port=content["port"], server_lvm=content["en_lvm"], service=service_dict).save()
        # except Exception, e:
        #    return HttpResponse(e)
        messages.info(request,  "添加主机信息成功!", fail_silently=True)
        return HttpResponse(0)
        # return redirect('/')
    else:
        default_service = []
        for s in Service.objects():
            default_service.append(s._id)
        return render(request, "add_host.html", {'default_services': default_service})


def convert_boolean(checked_string):
    """
    Javascript get the checkbox values are true/false, need convert to True/False.
    :param checked_string: checkbox values, eg: true or false.
    :return: True, False.
    """
    if checked_string.lower() == 'true':
        return True
    else:
        return False


def add_service(add_list, host_id):
    """
    add service for the specific host.
    :param add_list: services list, eg: ['nginx','mysql']
    :param host_id: host-name, eg: 'srv-nc-test10'
    :return: the count of updated, 即 matched_count
    """
    for i in add_list:
        service_key = "service." + i
        default_value = get_service_default(i.strip())
        try:
            add_result = update_para_value(host_id=host_id, para_name=service_key, para_value=default_value)
            update_add = add_result.acknowledged
        except pymongo.errors.InvalidOperation:
            update_add = False
            continue
    return update_add


def del_service(del_list, host_id):
    """
    delete specific services base on del_list and host_id
    :param del_list: services list, eg: ['nginx', 'apache']
    :param host_id: host-name, eg: 'srv-nc-test10'
    :return: updated matched_count
    """
    for i in del_list:
        service_key = "service." + i
        try:
            del_result = delete_host_service(host_id=host_id, service=service_key)
            update_del = del_result.acknowledged
        except pymongo.errors.InvalidOperation:
            update_del = False
            continue
    return update_del


@login_required()
# url: /update_host/,  GET & POST
def update_host(request):
    """
    request.GET["id"], host_name
    Update host_ip, port, server_lvm, and add or delete services for this server.
    """
    if request.method == "GET":
        host_name = request.GET["id"]
        host_info = Host.objects(_id=host_name)[0]
        # catch default services
        default_service = []
        for s in Service.objects():
            default_service.append(s._id)
        return render(request, "update_host.html", {"host": host_info, 'default_services': default_service})
    else:
        host_doc = request.POST
        ser_lvm = convert_boolean(host_doc["server_lvm"])
        result = Host.objects(_id=host_doc["_id"])[0].update(server_lvm=ser_lvm, ip=host_doc["ip"], port=host_doc["port"])

        now_list = host_doc['service']
        now_list = re.sub(r'\s', '', now_list)   # delete any whitespace character.
        now_list = now_list.split(',')
        now_list = [i for i in now_list if i.strip()]
        service_list = get_service_key(host_doc['_id'])

        if service_list and now_list:
            add_list = list(set(now_list) - set(service_list))
            del_list = list(set(service_list) - set(now_list))
            if add_list:
                # insert new service
                update_add = add_service(add_list=add_list, host_id=host_doc['_id'])
            if del_list:
                # delete service
                update_del = del_service(del_list=del_list, host_id=host_doc['_id'])
        elif service_list and not now_list:
            # delete all services
            update_del = del_service(del_list=service_list, host_id=host_doc['_id'])
        elif not service_list and now_list:
            # insert new services
            update_add = add_service(add_list=now_list, host_id=host_doc['_id'])
        elif not service_list and not now_list:
            pass

        # update_add, update_del are boolean type, get the value from add_service/del_service function.
        update_status = True
        if 'update_add' in locals():
            if not update_add:
                update_status = False
        if 'update_del' in locals():
            # print "update del num: " + str(update_del)
            if not update_del:
                update_status = False
        if (result == 1) and update_status:
            messages.info(request, "更新主机信息成功!", fail_silently=True)
        elif not update_status:
            messages.warning(request, "更新主机需要安装的服务失败!", fail_silently=True)
        info_detail = {'basic_update': result, 'service_update': update_status}
        return HttpResponse(json.dumps(info_detail))


@login_required()
# url: /update_service/ update service parameter value.
def update_service(request):
    """
    request.POST["service_parameters"]
    update specific service parameter
    eg, db.collection.update({_id: 'srv-nc-test10'}, {$set: {'service.apache.httpd_lvm_lv_name': www}})

    Using pymongo to update sub-document.
    """
    parameter_key = request.POST['para_key']
    parameter_val = request.POST['para_val']
    host_name, service, parameter = parameter_key.split('.')
    key = "service." + service + "." + parameter
    result = update_para_value(host_id=host_name, para_name=key, para_value=parameter_val)
    """
    Note modified_count is only reported by MongoDB 2.6 and later.
    When connected to an earlier server version,
    or in certain mixed version sharding configurations, this attribute will be set to None.
    So just return matched_count
    """
    return HttpResponse(result.matched_count)


def preview_config(request):
    customer_id = "123"
    info = []
    for host in Host.objects(customer_id=customer_id):
        info.append(host)
    ser_dict = {}
    for host_info in info:
        for s in host_info.service.keys():
            if s in ser_dict.keys():
                ser_dict[s][host_info._id] = host_info.service[s]
            else:
                ser_dict[s]={host_info._id: host_info.service[s]}
    return render(request, "preview.html", {"content": info, "services": ser_dict})
